package com.zyx.maildemo.config.jwt;

import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.zyx.maildemo.entity.Roles;
import com.zyx.maildemo.entity.User;
import com.zyx.maildemo.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @ClassName: JWTRealm
 * @author: zyx
 * @E-mail: 1377631190@qq.com
 * @DATE: 2019/7/27 14:20
 */
@Slf4j
public class JWTRealm extends AuthorizingRealm {

    @Autowired
    UserService userService;

    @Autowired
    private JWTUtils jwtUtils;

    @Override
    public boolean supports(AuthenticationToken token) {
        if (token instanceof JWTToken) {
            return true;
        }
        return super.supports(token);
    }

    /**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        String token = (String) principalCollection.getPrimaryPrincipal();
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addRole("user");
        String username = jwtUtils.getUsername(token);

        User user = userService.findByName(username);
        if (user != null) {
            List<String> collect = user.getRoles().stream()
                    .map(Roles::getSign)
                    .collect(Collectors.toList());
            info.addRoles(collect);
        }
        return info;
    }

    /**
     * 认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        JWTToken token = (JWTToken) authenticationToken;
        String jwtToken = token.getToken();
        String username = jwtUtils.getUsername(jwtToken);
        if (StringUtils.isEmpty(username)) {
            throw new AuthenticationException("无效Token");
        }

        User user = userService.findByName(username);
        if (null == user) {
            throw new UnknownAccountException("未知用户");
        }

        try {
            jwtUtils.verify(jwtToken, username, user.getPassword());
            return new SimpleAuthenticationInfo(jwtToken, jwtToken, getName());
        } catch (TokenExpiredException e) {
            throw new AuthenticationException("Token过期");
        } catch (JWTVerificationException e) {
            log.error("Token验证失败 {}", e.getMessage());
            throw new CredentialsException("验证失败！");
        }
    }
}
